<?php
/**
 * Created by PhpStorm.
 * User: front
 * Date: 2018/8/3
 * Time: 16:39
 */

namespace App\Services;

use App\Exceptions\ApiException;
use App\exption\hx_im\Hxim;
use App\Jobs\PushQueue;
use App\Jobs\StatisticsQueue;
use App\Jobs\UserQueue;
use App\Models\FailFriend;
use App\Models\Friend;
use App\Models\FriendModel;
use App\Models\HxUsers;
use App\Models\JpushMobile;
use App\Models\LoginLog;
use App\Models\RandDigitalPool;
use App\Models\Shareholder;
use App\Models\InviteInfo;
use App\Models\User;
use App\Models\UserInvitationCode;
use App\Models\UserTicket;
use App\Models\UserTickets;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\DB;
use App\Services\Pusher;
use Illuminate\Support\Facades\Redis;

class UserService
{

    /*
     * 新增/编辑用户黑名单
     * $userInfo 当前用户
     * $params 参数
     * */
    public static function option_fail_friend($userInfo, $params)
    {
        $where = [ ['uid', '=', $userInfo->id],['friend_uid', '=', $params['friend_uid']] ];
        $key = FailFriend::where($where)->delete();
        $rowsModel = FailFriend::getRows($where);
        if(empty($rowsModel)){
            $rowsModel = new FailFriend();
            $rowsModel->uid = $userInfo->id;
            $rowsModel->friend_uid = $params['friend_uid'];
        }
        $rowsModel->status = $params['status'];
        // 取消 关注状态
        $channel_friend_user_bool = Friend::change_status($userInfo, $params['friend_uid'], $params['status']);
        if(!$channel_friend_user_bool)
            return ['status'=>'error', 'message_code'=>10172, 'message'=>'改变关注状态失败'];
        // 取消亲友
        $channel_friend_bool = FriendModel::change_status($userInfo, $params['friend_uid'], $params['status']);
        if(!$channel_friend_user_bool)
            return ['status'=>'error', 'message_code'=>10172, 'message'=>'改变关注状态失败'];
        if(!$rowsModel->save())
            return ['status'=>'error', 'message_code'=>10000, 'message'=>'操作失败'];
        return ['status'=>'success', 'message_code'=>10000, 'message'=>'操作成功'];
    }

    /*
     * 登录生成ticket 和 校验是否发送极光下线通知
     *
     * $params array
     * $params['mobile_unique_code']  移动设备唯一标识
     * $params['registration_id']  极光id
     * */
    public static function login_send_jpush($userInfo, $params){

        $registration_id = IT('registration_id');
        $ClientSource = Input::get('ClientSource',3);
        $ClientSystem = Input::get('ClientSystem','MicroMessenger');

        if(empty($params) || !isset($params['mobile_unique_code']))
            return false;

        // 创建用户登录ticket
        $new_ticket =  $ticket = guid();
        $createTicket = self::createUserTicket($userInfo, $new_ticket);

        // 存储极光设备标识
        if(!empty($params['registration_id'])){
            JpushMobile::saveJpush($params);
            DB::table('users')->where('id', '=', $userInfo->id)->update(['registration_id'=>$params['registration_id']]);
        }

        if($createTicket){
            // 待作废
            cache(['ticket_'.$ClientSource.$userInfo->id => $ticket], config('basic.ticket_cache_time'));
            return $ticket;
        }

        return false;
    }

    /*
     * 生成新的ticket
     * */
    public static function createUserTicket($userInfo, $new_ticket)
    {
        $ClientSource = Input::get('ClientSource',3);
        $ClientSystem = Input::get('ClientSystem','MicroMessenger');

        $model = UserTickets::where([['uid', '=', $userInfo->id]])->first();
        if(empty($model)){
            $model = new UserTickets();
            $model->uid = $userInfo->id;
            $model->created_at = date('Y-m-d H:i:s',time());
        }else{
            // 删除旧ticket
            $old_key = 'user:login:'.md5($model->ticket);
            $key = Redis::del($old_key);
        }

        $model->ticket = $new_ticket;
        $model->status = 1;
        $model->client_source = $ClientSource;
        $model->client_system = $ClientSystem;
        $model->ip_address = get_ip();
        $model->updated_at = date('Y-m-d H:i:s',time());
        if(!$model->save())
            EE('登陆失败！',0, 10083);

        // 生成登录信息
        $expires_in = rand(3600, 3600*24);
        $key = 'user:login:'.md5($new_ticket);
        Redis::setex($key, $expires_in, json_encode($model));
        return $model;
    }

    /*
     * 绑定推送渠道
     * */
    public static function bindPushChannel($ticket, $client_source, $registration_id)
    {
        // 判断是否登录
        $userTecketRows = UserTicket::where([['ticket', '=', $ticket], ['client_source', '=', $client_source], ['status', '=', '1']])->first();
        if(!empty($userTecketRows)){
            User::where([['id', '=', $userTecketRows->uid]])->update(['registration_id'=>$registration_id]);
        }
    }

    /*
     * 获取股东资料
     * */
    public static function getShareholder($mobile)
    {
        return Shareholder::where([['mobile', '=', $mobile]])->orderBy('id', 'desc')->first();
    }

    /*
     *
     * 校验是否加入黑名单
     * @$uid 用户
     * @$friend_uid 好友用户
     * @$type 1 添加关注 2:添加亲友 3：通过亲友申请
     *
     * */
    public static function check_fail_friend($uid, $friend_uid,$type=1)
    {
        $model = new FailFriend();
        $sql = "select id,uid from " . $model->getTable() . " where ((uid=? and friend_uid=?) or (uid=? and friend_uid=?) ) and status=1";
        $list = DB::select($sql, [$uid, $friend_uid, $friend_uid, $uid]);
        $error_msg = [];

        if (!empty($list)){
            foreach($list as $item){
                if($item->uid == $uid){
                    $fail_friend_model = FailFriend::getRows([['uid', '=', $uid], ['friend_uid', '=', $friend_uid]]);
                    $fail_friend_model->status = 2;
                    $fail_friend_model->save();
                }else{
                    $type_str = ($type == 1) ? '关注' : '亲友圈';
                    $message_code = ($type == 1) ? 10247 : 10248;
                    // 当前用户把朋友拉黑    --其他是  朋友把自己拉黑了
                    $error_msg[] = '您已在对方黑名单列表中，暂不能添加'.$type_str;
                }
            }

            // 在对方黑名单中
            if(!empty($error_msg))
                return ['status'=>1, 'message_code'=>$message_code, 'message'=>implode(',', $error_msg)];
        }
        return ['status'=>0, 'message_code'=>10173, 'message'=>'不存在黑名单'];
    }

    /*
     * 创建分享信息
     * @$type : 默认微信分享
     * @$uid : 分享用户uid
     * @$operation_id : 业务id：微信openid ，手机号等
     * */
    public static function create_share_info($type=1, $uid, $operation_id)
    {
        $invite_info_model = new InviteInfo();
        $invite_info_model->type = $type;
        $invite_info_model->uid = $uid;
        $invite_info_model->operation_id = (string)$operation_id;
        $invite_info_model->create_time = time();

        if(!$invite_info_model->save())
            return false;
        return true;
    }

    /*
     * 检测是否在线
     * */
    public static function check_online()
    {
        $ticket = IT('ticket');
        $ClientSource = IT('ClientSource');
        if(!empty($ticket)){

            $rows = UserTickets::select('uid')->where([['ticket', '=', $ticket], ['client_source', '=', $ClientSource], ['status', '=', 1]])->first();
            if(!empty($rows)){
                $uid = $rows->uid;
                $key = config('feild.redis.check_online')."".date("Ymd", time()).":".$uid;
                if(empty(Redis::get($key))){
                    // 埋点登录日志
                    $login_log_model = new LoginLog();
                    $login_log_model->uid = $uid;
                    $login_log_model->create_time = time();
                    $login_log_model->save();

                    $user_statisctics = ['action'=>'user_login', 'data'=>['uid'=>$uid, 'create_time'=>time(), 'login_log_id'=>$login_log_model->id]];
                    dispatch((new StatisticsQueue($user_statisctics))->onQueue('statistics'));
                    Redis::setex($key, (24*3600), 1);
                }
            }
        }
    }

    /*
     * 生成用户二维码编码
     * */
    public static function create_user_code($uid)
    {
        DB::beginTransaction();
        try {
            if (empty($uid))
                throw new \Exception('未知用户');
            $user_rows = User::where([['id', '=', $uid]])->first();
            if (empty($user_rows))
                throw new \Exception('用户不存在');

            $uic_rows = UserInvitationCode::where([['uid', '=', $uid]])->first();
            if (!empty($uic_rows))
                throw new \Exception('该用户已创建用户编码');

            $rand_digital_pool_rows = RandDigitalPool::select('number', 'id')->where([['status', '=', '0']])->orderBy('id', 'asc')->first();
            if (empty($rand_digital_pool_rows))
                throw new \Exception('获取用户编码失败');

            // 判断该编码是否被暂用
            $uic_rows = UserInvitationCode::where([['invitation_code', '=', $rand_digital_pool_rows->number]])->first();
            if(!empty($uic_rows)){
                RandDigitalPool::where([['id', '=', $rand_digital_pool_rows->id]])->update(['status' => 1]);
                DB::commit();
                // 重新创建队列
                self::create_user_queue($uid);
                return true;
            }

            $user_code_key = config('feild.user_code') . $rand_digital_pool_rows->number;
            if (!empty(Redis::get($user_code_key))) {
                $expires_in = 3;
                Redis::setex($user_code_key, $expires_in, $rand_digital_pool_rows->number);

                // 重新创建队列
                self::create_user_queue($uid);
                throw new \Exception('用户编码已被暂用');
            }

            $uic_model = new UserInvitationCode();
            $uic_model->uid = $uid;
            $uic_model->invitation_code = $rand_digital_pool_rows->number;
            if (!$uic_model->save()) {
                // 重新创建队列
                self::create_user_queue($uid);
                throw new \Exception('保存用户编码有误');
            }

            $update = RandDigitalPool::where([['id', '=', $rand_digital_pool_rows->id]])->update(['status' => 1]);
            if (!$update) {
                // 重新创建队列
                self::create_user_queue($uid);
                throw new \Exception('更新随机编码异常');
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {

            // 监控数据
            $params = [['type' => config('feild.type.monitoring')[0]['id'], 'status' => 'error', 'params' => json_encode(['uid' => $uid]), 'content' => $e->getMessage(), 'created_at' => time2date(), 'uid' => $uid]];
            $result = insert_mongodb_log('ivy_monitoring', $params);
            DB::rollBack();
        }
    }

    /*
     * 注册环信用户
     * */
    public static function reg_hx_user($uid)
    {
        if(empty($uid))
            return false;

        $hx_im = new Hxim();
        $hx_im_prefix = config('basic.hx_im.hx_im_prefix');
        $username = $hx_im_prefix.$uid;

        // 获取环信用户
        $hx_user = self::get_hx_user($username);
        // 不存在用户
        if(!$hx_user){
            // 注册用户
            $post['username'] = $username;
            $post['password'] = md5('ivy1fodfsf!@#'.$username);
            $post['nickname'] = config('basic.hx_im.hx_im_prefix').'_nickname'.$uid;
            $data = $hx_im->curl_post_json('users', $post);
            if(empty($data))
                return false;
            $reg_hx_user = json_decode($data, true);
            if($hx_im->http_code == 200){
                if(isset($reg_hx_user['entities']))
                    $hx_user = $reg_hx_user['entities'][0];
            }else{
                $key = 'errpr:reg:hx:';
                Redis::setex($key.date("YmdHis", time()), (3600*24*7), json_encode($reg_hx_user));
            }
        }

        // 平台添加环信账号
        if(!empty($hx_user)){
            $hx_user['password'] = md5('ivy1fodfsf!@#'.$username);
            // 判断环信用户是否存在
            $hx_rows = HxUsers::where([['uid', '=', $uid]])->first();
            if(!empty($hx_rows))
                return $hx_user;

            $hx_user_model = new HxUsers();
            if($hx_user_model->add($uid, $hx_user))
                return $hx_user;
        }

        return false;
    }

    /*
     * 创建用户队列
     *
     * 1个用户1小时创建10次
     *
     * */
    public static function create_user_queue($uid)
    {
        // 休眠5秒
        sleep(5);
        $create_user_code_num_key = config('feild.create_user_code_num') . $uid;
        if (empty(Redis::get($create_user_code_num_key)) || (Redis::get($create_user_code_num_key) < 10)) {
            // 创建用户队列
            $user_queue = ['action' => 'create_user_code', 'data' => ['uid' => $uid, 'create_time' => time()]];
            dispatch((new UserQueue($user_queue))->onQueue('user_queue'));
        }

        Redis::incr($create_user_code_num_key);
        Redis::expire($create_user_code_num_key, 3600);
    }

    /*
     * 获取环信用户
     * */
    public static function get_hx_user($username)
    {
        $hx_im = new Hxim();
        $get_hx_user_url = $hx_im->base_url.'/'.$hx_im->org_name.'/'.$hx_im->app_name.'/users/'.$username;

        $hx_user = $hx_im->curl_get_json($get_hx_user_url);
        if($hx_im->http_code == 200){
            $hx_user_data = json_decode($hx_user, true);
            if(isset($hx_user_data['entities']))
                return $hx_user_data['entities'][0];
        }
        return false;
    }

}